﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfPdfReader
{
    /// <summary>
    /// LabPdfReaderControl.xaml 的交互逻辑
    /// </summary>
    public partial class LabPdfReaderControl : UserControl, IDisposable
    {
        private MupdfSharp.PdfRenderRealtime pdfrender = null;
        public event EventHandler<OpenCompletedEventArgs> OpenCompleted;
        public event EventHandler<ViewTypeChangedEventArgs> ViewTypeChanged;

        public LabPdfReaderControl()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(LabPdfReaderControl_Loaded);
            this.OpenCompleted += new EventHandler<OpenCompletedEventArgs>(LabPdfReaderControl_OpenCompleted);
            this.ViewTypeChanged += new EventHandler<ViewTypeChangedEventArgs>(LabPdfReaderControl_ViewTypeChanged);
            recentItemControl.ItemSelectionChanged += new EventHandler<RecentItemControl.FileItemSelectionChangedEventArgs>(recentItemControl_ItemSelectionChanged);
            recentItemControl.Open += new RoutedEventHandler(recentItemControl_Open);
            AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
        }

        void CurrentDomain_ProcessExit(object sender, EventArgs e)
        {
            if (this.pdfrender != null)
            {
                this.recentItemControl.AddFileItem(this.FileName, this.pdfrender.CurrentPage, this.pdfrender.CurrentPageBitmap);
                this.recentItemControl.Serialize();
                this.pdfrender.Close();
            }
            this.Dispose();
        }

        void OnViewTypeChanged(ViewTypeChangedEventArgs e)
        {
            if (this.ViewTypeChanged != null)
            {
                this.ViewTypeChanged(this, e);
            }
        }

        void LabPdfReaderControl_ViewTypeChanged(object sender, ViewTypeChangedEventArgs e)
        {
            if (e.View == ViewType.ReadView)
            {
                imageBorder.Child = MasterScrollViewer;

                this.btnPrevious.IsEnabled = true;
                this.btnNext.IsEnabled = true;
                this.btnZoomIn.IsEnabled = true;
                this.btnZoomOut.IsEnabled = true;
                this.textPage.IsEnabled = true;
            }
            else if (e.View == ViewType.Catalog)
            {
                imageBorder.Child = recentItemControl;

                this.btnPrevious.IsEnabled = false;
                this.btnNext.IsEnabled = false;
                this.btnZoomIn.IsEnabled = false;
                this.btnZoomOut.IsEnabled = false;
                this.textPage.IsEnabled = false;
            }
        }

        void LabPdfReaderControl_OpenCompleted(object sender, OpenCompletedEventArgs e)
        {
            this.btnGoBack.IsEnabled = true;
            this.EnableGoBack = true;
            this.IsGoBack = false;

            bool IsAdded = false;
            foreach (MenuItem item in this.contextMenu.Items)
            {
                if (item.Header.ToString() == FileName)
                {
                    IsAdded = true;
                    break;
                }
            }
            if (!IsAdded)
            {
                MenuItem newItem = new MenuItem() { Header = FileName };
                newItem.Icon = new Image() { Width = 16, Height = 16, Source = BrushHelper.GetBitmapImage(new Uri("images/PushPin.png", UriKind.Relative)) };

                newItem.Click += new RoutedEventHandler((menuItem, args) =>
                {
                    string fileName = (menuItem as MenuItem).Header.ToString();
                    Open(fileName);
                });

                this.contextMenu.Items.Add(newItem);
            }

            this.recentItemControl.AddFileItem(FileName, this.pdfrender.CurrentPageBitmap);

            this.View = ViewType.ReadView;
        }

        RecentItemControl recentItemControl = new RecentItemControl();
        void LabPdfReaderControl_Loaded(object sender, RoutedEventArgs e)
        {
            if (recentItemControl.HasItem && string.IsNullOrEmpty(this.FileName))
            {
                this.View = ViewType.Catalog;
            }
        }

        void recentItemControl_Open(object sender, RoutedEventArgs e)
        {
            this.OpenPdf_Click(sender, e);
        }

        void recentItemControl_ItemSelectionChanged(object sender, RecentItemControl.FileItemSelectionChangedEventArgs e)
        {
            string fileName = e.Item.FullName;
            if (System.IO.File.Exists(fileName))
            {
                Open(fileName);
            }
            else
            {
                MessageBox.Show(fileName + "\n不存在", "提示", MessageBoxButton.OK, MessageBoxImage.Question);
            }
        }

        public bool Open(string fileName)
        {
            if (this.FileName == fileName && (!string.IsNullOrEmpty(fileName)))
            {
                this.View = ViewType.ReadView;
                if (OpenCompleted != null)
                    OpenCompleted(this, new OpenCompletedEventArgs(FileName));
                return true;
            }
            else if (System.IO.File.Exists(fileName))
            {
                this.HWPercent = 0.0f;

                if (this.pdfrender != null)
                {
                    this.recentItemControl.AddFileItem(this.FileName, this.pdfrender.CurrentPage, this.pdfrender.CurrentPageBitmap);
                }
                pdfrender = new MupdfSharp.PdfRenderRealtime();
                try
                {
                    if (pdfrender.OpenFile(fileName, new System.Drawing.SizeF((float)this.MasterScrollViewer.ActualWidth, (float)(this.MasterScrollViewer.ActualHeight))))
                    {
                        var fileItem = this.recentItemControl.FindItem(fileName);
                        if (fileItem != null && fileItem.Page > 0)
                        {
                            WindowPrompt win = new WindowPrompt(fileItem);
                            if (win.ShowDialog().Value)
                            {
                                GoToPage(fileItem.Page + 1);
                            }
                            else
                            {
                                GotoFirstPage();
                            }
                        }
                        else
                        {
                            GotoFirstPage();
                        }

                        this.FileName = fileName;

                        if (OpenCompleted != null)
                            OpenCompleted(this, new OpenCompletedEventArgs(FileName));

                        return true;
                    }
                    else
                    {
                        pdfrender.Close();
                        pdfrender = null;
                        return false;
                    }
                }
                catch
                {
                    pdfrender.Close();
                    pdfrender = null;
                    return false;
                }
            }
            else
                return false;
        }

        private string fileName = "";
        public string FileName
        {
            set
            {
                if (value != fileName)
                    fileName = value;
            }
            get
            {
                return fileName;
            }
        }

        private ViewType viewType = ViewType.None;
        public ViewType View
        {
            get { return this.viewType; }
            set
            {
                if (value != this.viewType)
                {
                    this.viewType = value;
                    OnViewTypeChanged(new ViewTypeChangedEventArgs(value));
                }
            }
        }

        public void GotoFirstPage()
        {
            if (this.pdfrender != null)
            {
                this.pdfrender.GotoFirstPage();
                SetImage();
            }
        }
        private double VerticalOffset = Math.Pow(10, -10);
        private void SetImage()
        {
            if (this.HWPercent == 0)
            {
                this.HWPercent = this.pdfrender.CurrentScale;
                this.currentPercent = this.HWPercent;
            }
            this.image.Source = ImageSourceHelper.ImageToSource(this.pdfrender.CurrentPageBitmap);
            this.textPage.Text = string.Format("{0}/{1}", this.pdfrender.CurrentPage + 1, this.pdfrender.PageCount);
            //this.MasterScrollViewer.ScrollToTop();
            if (this.MasterScrollViewer.VerticalOffset != this.VerticalOffset)
                this.MasterScrollViewer.ScrollToVerticalOffset(VerticalOffset);
        }

        public void GotoLastPage()
        {
            if (this.pdfrender != null)
            {
                this.pdfrender.GotoLastPage();
                SetImage();
            }
        }

        public void GotoNextPage()
        {
            if (this.pdfrender != null)
            {
                this.pdfrender.GotoNextPage();
                SetImage();
            }
        }

        public void GotoPreviousPage()
        {
            if (this.pdfrender != null)
            {
                this.pdfrender.GotoPreviousPage();
                SetImage();
            }
        }

        public void GoToPage(int page)
        {
            if (this.pdfrender != null)
            {
                this.pdfrender.SetCurrentPage(page - 1);
                SetImage();
            }
        }

        private void btnFirst_MouseDown(object sender, MouseButtonEventArgs e)
        {
            GotoFirstPage();
        }

        /// <summary>
        /// 显示第一张页面时长宽缩放比例
        /// </summary>
        private float HWPercent = 0.0f;
        /// <summary>
        /// 当前页面长宽缩放比例
        /// </summary>
        private float currentPercent = 0.0f;

        private void btnPrevious_MouseUp(object sender, MouseButtonEventArgs e)
        {
            GotoPreviousPage();
        }

        private void btnNext_MouseUp(object sender, MouseButtonEventArgs e)
        {
            GotoNextPage();
        }

        private bool EnableGoBack = false;
        private bool IsGoBack = false;

        public void GoBack()
        {
            if (this.EnableGoBack)
            {
                if (!IsGoBack)
                {
                    IsGoBack = true;
                    this.View = ViewType.Catalog;
                }
                else
                {
                    IsGoBack = false;
                    this.View = ViewType.ReadView;
                }
            }
        }

        private void btnGoBack_MouseUp(object sender, MouseButtonEventArgs e)
        {
            this.GoBack();
        }

        #region 通过鼠标进行 缩放、平移图片

        private bool m_IsMouseLeftButtonDown;
        private Point m_PreviousMousePoint;

        private void MasterImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //var rectangle = sender as ContentControl;
            //if (rectangle == null) return;
            //rectangle.CaptureMouse();
            //m_IsMouseLeftButtonDown = true;
            //m_PreviousMousePoint = e.GetPosition(rectangle);
        }

        private void MasterImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            //var rectangle = sender as ContentControl;
            //if (rectangle == null) return;
            //rectangle.ReleaseMouseCapture();
            //m_IsMouseLeftButtonDown = false;
        }

        private void MasterImage_MouseMove(object sender, MouseEventArgs e)
        {
            //var rectangle = sender as ContentControl;
            //if (rectangle == null) return;
            //if (m_IsMouseLeftButtonDown)
            //    DoImageMove(rectangle, e);
        }

        private void DoImageMove(ContentControl rectangle, MouseEventArgs e)
        {
            if (e.LeftButton != MouseButtonState.Pressed) return;
            var group = imageBorder.FindResource("ImageTransformResource") as TransformGroup;
            var transform = group.Children[1] as TranslateTransform;
            var position = e.GetPosition(rectangle);
            transform.X += position.X - m_PreviousMousePoint.X;
            transform.Y += position.Y - m_PreviousMousePoint.Y;
            m_PreviousMousePoint = position;
        }

        private void MasterImage_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            //var image = sender as ContentControl;
            //if (image == null) return;
            //var group = imageBorder.FindResource("ImageTransformResource") as TransformGroup;
            //var point = e.GetPosition(image);
            //var scale = e.Delta * 0.001;
            //currentPercent += (float)scale;
            //if (currentPercent < this.HWPercent)
            //    currentPercent = this.HWPercent;
            //this.pdfrender.ScalePage(currentPercent);
            //SetImage();
            // ZoomImage(group, point, scale);
        }

        #endregion


        private void btnZoomIn_MouseUp(object sender, MouseButtonEventArgs e)
        {
            ZoomIn();
        }

        #region 多点触摸操作

        private void image_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
        {
            e.ManipulationContainer = touchPad;
            e.Mode = ManipulationModes.All;
        }

        private void image_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)e.Source;
            element.Opacity = 0.6;

            Matrix matrix = (((TransformGroup)element.RenderTransform).Children[2] as MatrixTransform).Matrix;

            var deltaManipulation = e.DeltaManipulation;

            Point center = new Point(element.ActualWidth / 2, element.ActualHeight / 2);
            center = matrix.Transform(center);

            this.pdfrender.ScalePage((float)(deltaManipulation.Scale.X + deltaManipulation.Scale.Y) / 2);
            SetImage();

            matrix.ScaleAt(deltaManipulation.Scale.X, deltaManipulation.Scale.Y, center.X, center.Y);

            matrix.RotateAt(e.DeltaManipulation.Rotation, center.X, center.Y);

            matrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y);

            ((MatrixTransform)element.RenderTransform).Matrix = matrix;
        }

        private void image_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
        {
            FrameworkElement element = (FrameworkElement)e.Source;
            element.Opacity = 1;
        }

        /// <summary>
        /// 惯性操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void image_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e)
        {
            e.TranslationBehavior = new InertiaTranslationBehavior();
            e.TranslationBehavior.InitialVelocity = e.InitialVelocities.LinearVelocity;
            e.TranslationBehavior.DesiredDeceleration = 10.0 * 96.0 / (1000.0 * 1000.0);

            e.ExpansionBehavior = new InertiaExpansionBehavior();
            e.ExpansionBehavior.InitialVelocity = e.InitialVelocities.ExpansionVelocity;
            e.ExpansionBehavior.DesiredDeceleration = 0.1 * 96 / 1000.0 * 1000.0;

            e.RotationBehavior = new InertiaRotationBehavior();
            e.RotationBehavior.InitialVelocity = e.InitialVelocities.AngularVelocity;
            e.RotationBehavior.DesiredDeceleration = 720 / (1000.0 * 1000.0);
        }

        #endregion

        private void btnZoomOut_MouseUp(object sender, MouseButtonEventArgs e)
        {
            ZoomOut();
        }
        /// <summary>
        /// 以25%的比例放大
        /// </summary>
        public void ZoomIn()
        {
            currentPercent += currentPercent * 0.25f;
            this.pdfrender.ScalePage(currentPercent);

            this.enableScroll = false;
            SetImage();
            this.enableScroll = true;
        }
        /// <summary>
        /// 以25%的比例缩小
        /// </summary>
        public void ZoomOut()
        {
            currentPercent -= currentPercent * 0.25f;
            if (currentPercent < HWPercent)
                currentPercent = HWPercent;
            this.pdfrender.ScalePage(currentPercent);

            this.enableScroll = false;
            SetImage();
            this.enableScroll = true;
        }

        private void OpenPdf_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog openDlg = new Microsoft.Win32.OpenFileDialog();
            openDlg.Filter = "PDF File(*.pdf)|*.pdf";
            if (openDlg.ShowDialog(Owner).Value)
            {
                Open(openDlg.FileName);
            }
        }

        private static Window owner = null;
        private static Window Owner
        {
            get
            {
                WindowCollection wins = Application.Current.Windows;
                foreach (Window win in wins)
                {
                    if (win.IsActive)
                    {
                        owner = win;
                        break;
                    }
                }
                return owner;
            }
        }

        #region CommandBindings 事件处理

        private void ZoomIn_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.ZoomIn();
        }

        private void ZoomOut_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.ZoomOut();
        }

        private void CZoomIn_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void CZoomOut_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        #endregion

        private void UserControl_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            //if (e.Key == Key.PageDown || e.Key == Key.Right || e.Key == Key.L || e.Key == Key.K  || e.Key == Key.S)
            //    this.GotoNextPage();
            //else if (e.Key == Key.PageUp || e.Key == Key.Left || e.Key == Key.J || e.Key == Key.I  || e.Key == Key.A)
            //    this.GotoPreviousPage();
            //else if (e.Key == Key.Home)
            //    this.GotoFirstPage();
            //else if (e.Key == Key.End)
            //    this.GotoLastPage();
            //else if (e.Key == Key.F)
            //    this.ZoomIn();
            //else if (e.Key == Key.D)
            //    this.ZoomOut();

        }

        public void ScrollToHome()
        {
            double offset = this.MasterScrollViewer.VerticalOffset - 20;
            this.MasterScrollViewer.ScrollToVerticalOffset(offset);
        }
        public void ScrollToBottom()
        {
            double offset = this.MasterScrollViewer.VerticalOffset + 20;
            this.MasterScrollViewer.ScrollToVerticalOffset(offset);
        }
        public void ScrollToRight()
        {
            double offset = this.MasterScrollViewer.HorizontalOffset + 10;
            this.MasterScrollViewer.ScrollToHorizontalOffset(offset);
        }
        public void ScrollToLeft()
        {
            double offset = this.MasterScrollViewer.HorizontalOffset - 10;
            this.MasterScrollViewer.ScrollToHorizontalOffset(offset);
        }

        public void AddBookMark()
        {
            WindowAddBookmark win = new WindowAddBookmark();
            if (win.ShowDialog().Value)
            {
                this.recentItemControl.AddBookMark(this.FileName, win.BookMarkName, this.pdfrender.CurrentPage, this.pdfrender.CurrentPageBitmap, win.Note);
            }
        }

        public void ShowBookManager()
        {
            WindowBookManager win = new WindowBookManager(this.recentItemControl.GetBookMarks(this.FileName));
            win.GoToBookMark += new EventHandler<BookMarkEventArgs>(win_GoToBookMark);
            win.ShowDialog();
        }

        void win_GoToBookMark(object sender, BookMarkEventArgs e)
        {
            this.GoToPage(e.Page + 1);
        }

        private void textPage_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (this.pdfrender != null)
            {
                if (e.Key == Key.Return)
                {
                    int page;
                    int.TryParse(this.textPage.Text, out page);
                    this.GoToPage(page);
                    this.Focus();
                }
            }
        }

        private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (this.pdfrender != null)
            {
                if (this.pdfrender.CurrentPageBitmap.Width > e.NewSize.Width || this.pdfrender.CurrentPageBitmap.Height > e.NewSize.Height)
                    return;
                this.pdfrender.SetPageSize(new System.Drawing.SizeF((float)e.NewSize.Width, (float)e.NewSize.Height));
                this.pdfrender.SetCurrentPage(this.pdfrender.CurrentPage);
                this.SetImage();
                this.HWPercent = this.pdfrender.CurrentScale;
            }
        }

        private void UserControl_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
                if (files != null && files.Length > 0)
                {
                    string fileName = files[0];
                    if (System.IO.Path.GetExtension(fileName).ToUpper() == ".PDF")
                    {
                        e.Effects = DragDropEffects.All;
                    }
                    else
                        e.Effects = DragDropEffects.None;
                }
                else
                    e.Effects = DragDropEffects.None;
            }
        }

        private void UserControl_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
                if (files != null && files.Length > 0)
                {
                    string fileName = files[0];
                    if (System.IO.Path.GetExtension(fileName).ToUpper() == ".PDF")
                    {
                        this.Open(fileName);
                    }
                }
            }
        }

        private void CExportImage_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            string pictureFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            string appFolder = System.IO.Path.Combine(pictureFolder, "WpfPdfReader");
            if (!System.IO.Directory.Exists(appFolder))
                System.IO.Directory.CreateDirectory(appFolder);

            string fileFolder = System.IO.Path.Combine(appFolder, System.IO.Path.GetFileNameWithoutExtension(this.FileName));
            if (!System.IO.Directory.Exists(fileFolder))
                System.IO.Directory.CreateDirectory(fileFolder);

            string imgName = System.IO.Path.Combine(fileFolder, string.Format("{0}.png", this.pdfrender.CurrentPage + 1));
            this.pdfrender.CurrentPageBitmap.Save(imgName);
            MessageBox.Show("图片保存在\n" + imgName + "\n", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
        }

        private void CExportImage_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (this.View == ViewType.ReadView)
                e.CanExecute = this.pdfrender.CurrentPageBitmap != null;
            else
                e.CanExecute = false;
        }
        private CacheMapManager CacheBmps = CacheMapManager.Instance;
        private bool enableScroll = false;
        private void MasterScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            if (!this.enableScroll)
                return;
            if (e.VerticalOffset == 0)
            {
                if (this.pdfrender.CurrentPage > 0)
                {
                    if (this.pdfrender.CurrentPage == this.pdfrender.PageCount - 1)
                    {
                        this.pdfrender.SetCurrentPage(this.pdfrender.CurrentPage - 1);
                    }
                    BitmapImage bitmapImage = null;
                    string key = string.Format("{0}_{1}_{2}_{3}", System.IO.Path.GetFileNameWithoutExtension(this.FileName), this.pdfrender.CurrentPage - 1, this.pdfrender.CurrentPage, this.pdfrender.CurrentScale);

                    System.Drawing.Image image1 = this.pdfrender.CurrentPageBitmap;
                    int imageHeight = image1.Height;
                    this.pdfrender.SetCurrentPage(this.pdfrender.CurrentPage - 1);
                    if (!this.CacheBmps.ContainsKey(key))
                    {
                        System.Drawing.Image image2 = this.pdfrender.CurrentPageBitmap;
                        bitmapImage = BrushHelper.GetBitmapImageFromStream(ImageHelper.MergeImageVertical(image2, image1));
                        this.CacheBmps[key] = new CacheMapManager.CacheItem() { Key = key, BitmapImage = bitmapImage };
                        image1.Dispose();
                    }
                    else
                        bitmapImage = this.CacheBmps[key].BitmapImage;

                    this.image.Source = bitmapImage;
                    this.textPage.Text = string.Format("{0}/{1}", this.pdfrender.CurrentPage + 1, this.pdfrender.PageCount);

                    this.MasterScrollViewer.ScrollToVerticalOffset(imageHeight);
                }

            }
            else
            {
                if (e.VerticalOffset + e.ViewportHeight <= e.ExtentHeight && e.VerticalOffset + e.ViewportHeight > e.ExtentHeight - 0.0001)
                {
                    if (this.pdfrender.CurrentPage < this.pdfrender.PageCount - 1)
                    {
                        BitmapImage bitmapImage = null;
                        string key = string.Format("{0}_{1}_{2}_{3}", System.IO.Path.GetFileNameWithoutExtension(this.FileName), this.pdfrender.CurrentPage, this.pdfrender.CurrentPage + 1, this.pdfrender.CurrentScale);

                        System.Drawing.Image image1 = this.pdfrender.CurrentPageBitmap;
                        int imageHeight = image1.Height;
                        this.pdfrender.SetCurrentPage(this.pdfrender.CurrentPage + 1);
                        if (!this.CacheBmps.ContainsKey(key))
                        {
                            System.Drawing.Image image2 = this.pdfrender.CurrentPageBitmap;
                            bitmapImage = BrushHelper.GetBitmapImageFromStream(ImageHelper.MergeImageVertical(image1, image2));
                            this.CacheBmps[key] = new CacheMapManager.CacheItem() { Key = key, BitmapImage = bitmapImage };
                            image1.Dispose();
                        }
                        else
                            bitmapImage = this.CacheBmps[key].BitmapImage;

                        this.image.Source = bitmapImage;
                        this.textPage.Text = string.Format("{0}/{1}", this.pdfrender.CurrentPage + 1, this.pdfrender.PageCount);

                        this.MasterScrollViewer.ScrollToVerticalOffset(imageHeight - e.ViewportHeight + VerticalOffset);
                    }
                }
            }
        }

        private void MasterScrollViewer_MouseEnter(object sender, MouseEventArgs e)
        {
            this.enableScroll = true;
        }

        private void MasterScrollViewer_MouseLeave(object sender, MouseEventArgs e)
        {
            this.enableScroll = false;
        }

        public void Dispose()
        {
            this.CacheBmps.Dispose();
        }

        private void CExportAllImage_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //string pictureFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            //string appFolder = System.IO.Path.Combine(pictureFolder, "WpfPdfReader");
            //if (!System.IO.Directory.Exists(appFolder))
            //    System.IO.Directory.CreateDirectory(appFolder);

            //string fileFolder = System.IO.Path.Combine(appFolder, System.IO.Path.GetFileNameWithoutExtension(this.FileName));
            //if (!System.IO.Directory.Exists(fileFolder))
            //    System.IO.Directory.CreateDirectory(fileFolder);

            ////转到第一页
            //this.pdfrender.GotoFirstPage();
            //for (int i = 0; i < this.pdfrender.PageCount; i++)
            //{
            //    string imgName = System.IO.Path.Combine(fileFolder, string.Format("{0}.png", this.pdfrender.CurrentPage + 1));
            //    this.pdfrender.CurrentPageBitmap.Save(imgName);
            //    this.pdfrender.GotoNextPage();
            //}
            //MessageBox.Show("图片保存在\n" + fileFolder + "\n", "提示", MessageBoxButton.OK, MessageBoxImage.Information);

            WindowProgressBar winProgressbar = new WindowProgressBar();
            winProgressbar.Init(this.pdfrender.PageCount, ExportAllImage);
            winProgressbar.Owner = Owner;
            winProgressbar.ShowDialog();


        }

        private string GetSaveFileFolder()
        {
            string pictureFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            string appFolder = System.IO.Path.Combine(pictureFolder, "WpfPdfReader");
            if (!System.IO.Directory.Exists(appFolder))
                System.IO.Directory.CreateDirectory(appFolder);

            string fileFolder = System.IO.Path.Combine(appFolder, System.IO.Path.GetFileNameWithoutExtension(this.FileName));
            if (!System.IO.Directory.Exists(fileFolder))
                System.IO.Directory.CreateDirectory(fileFolder);

            return fileFolder;
        }

        private void ExportAllImage(int state, Action<string> updateStatusfunc)
        {
            updateStatusfunc("正在导出第 " + (state+1) + " 页  "+DateTime.Now.ToString());
            if (state == 0)
            {
                this.pdfrender.GotoFirstPage();

                string fileFolder = GetSaveFileFolder();
                string imgName = System.IO.Path.Combine(fileFolder, string.Format("{0}.png", this.pdfrender.CurrentPage + 1));
                this.pdfrender.CurrentPageBitmap.Save(imgName);

                this.pdfrender.GotoNextPage();
            }
            else if (state < this.pdfrender.PageCount - 1)
            {
                string fileFolder = GetSaveFileFolder();
                string imgName = System.IO.Path.Combine(fileFolder, string.Format("{0}.png", this.pdfrender.CurrentPage + 1));
                this.pdfrender.CurrentPageBitmap.Save(imgName);

                this.pdfrender.GotoNextPage();
            }
            else
            {
                string fileFolder = GetSaveFileFolder();
                string imgName = System.IO.Path.Combine(fileFolder, string.Format("{0}.png", this.pdfrender.CurrentPage + 1));
                this.pdfrender.CurrentPageBitmap.Save(imgName);

                MessageBox.Show("图片保存在\n" + fileFolder + "\n", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
            }
        }

        private void CExportAllImage_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (this.View == ViewType.ReadView)
                e.CanExecute = this.pdfrender.CurrentPageBitmap != null;
            else
                e.CanExecute = false;
        }
    }

    public enum ViewType
    {
        /// <summary>
        /// 未知
        /// </summary>
        None = -1,
        /// <summary>
        /// 阅读模式
        /// </summary>
        ReadView = 0,
        /// <summary>
        /// 列表目录
        /// </summary>
        Catalog = 1,
    }

    public class OpenCompletedEventArgs : EventArgs
    {
        public string FileName { get; set; }
        public OpenCompletedEventArgs(string fileName)
        {
            this.FileName = fileName;
        }
    }

    public class ViewTypeChangedEventArgs : EventArgs
    {
        public ViewType View { get; set; }
        public ViewTypeChangedEventArgs(ViewType viewType)
        {
            this.View = viewType;
        }
    }

    class CacheMapManager : IDisposable
    {
        private static readonly int MaxCount = 256;
        public List<CacheItem> Caches = null;
        private static CacheMapManager instance = new CacheMapManager();
        private CacheMapManager()
        {
            Caches = new List<CacheItem>();
        }

        public static CacheMapManager Instance
        {
            get { return instance; }
        }

        private void Add(CacheItem item)
        {
            if (Caches.Count < MaxCount)
                this.Caches.Add(item);
            else
            {
                CacheItem theFirstItem = this.Caches[0];
                this.Caches.Remove(theFirstItem);

                theFirstItem.Dispose();

                this.Caches.Add(item);
            }
        }

        public bool ContainsKey(string key)
        {
            foreach (var item in this.Caches)
            {
                if (item.Key == key)
                {
                    return true;
                }
            }
            return false;
        }

        public CacheItem this[string key]
        {
            get
            {
                foreach (var item in this.Caches)
                {
                    if (item.Key == key)
                    {
                        return item;
                    }
                }
                return CacheItem.Empty;
            }
            set
            {
                this.Add(value);
            }
        }

        public void Reset()
        {
            foreach (var item in this.Caches)
            {
                item.Dispose();
            }

            this.Caches.Clear();
        }

        public void Dispose()
        {
            this.Reset();
        }

        public class CacheItem : IEquatable<CacheItem>, IDisposable
        {
            public static readonly CacheItem Empty = new CacheItem() { Key = "", BitmapImage = null };

            private static readonly string Temp = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "WpfPdfReader");
            static CacheItem()
            {
                if (!System.IO.Directory.Exists(Temp))
                    System.IO.Directory.CreateDirectory(Temp);
            }
            public string Key { get; set; }

            private string bitmapFileName = "";
            public BitmapImage BitmapImage
            {
                set
                {
                    if (value != null)
                    {
                        bitmapFileName = System.IO.Path.Combine(Temp, this.Key + ".png");
                        System.Drawing.Image bitmap = System.Drawing.Bitmap.FromStream(value.StreamSource);
                        bitmap.Save(bitmapFileName, System.Drawing.Imaging.ImageFormat.Png);
                        bitmap.Dispose();
                    }
                }
                get
                {
                    BitmapImage bmp = null;
                    try
                    {
                        bmp = new BitmapImage();
                        bmp.BeginInit();
                        bmp.StreamSource = System.IO.File.OpenRead(bitmapFileName);
                        bmp.EndInit();
                    }
                    catch
                    {
                        bmp = null;
                    }
                    return bmp;
                }
            }

            public bool Equals(CacheItem other)
            {
                if (other == null)
                    return false;
                else
                    return this.Key == other.Key;
            }

            public static bool operator ==(CacheItem a, CacheItem b)
            {
                // If both are null, or both are same instance, return true.
                if (System.Object.ReferenceEquals(a, b))
                {
                    return true;
                }

                // If one is null, but not both, return false.
                if (((object)a == null) || ((object)b == null))
                {
                    return false;
                }

                // Return true if the fields match:
                return a.Key == b.Key && a.BitmapImage == b.BitmapImage;

            }

            public static bool operator !=(CacheItem a, CacheItem b)
            {
                return !(a == b);
            }

            public override bool Equals(object obj)
            {
                CacheItem item = obj as CacheItem;
                if (item == null)
                    return false;
                return base.Equals(obj) && this.Key == item.Key;
            }

            public override int GetHashCode()
            {
                return base.GetHashCode();
            }

            public void Dispose()
            {
                System.IO.File.Delete(this.bitmapFileName);
            }
        }
    }
}
